import numpy as np
import cv2


class Utils:

    @staticmethod
    def get_colors_lower_upper(color):
        """
        颜色区域
        :param color:[(),(),()]
        :return:
        """
        if not isinstance(color, list) or len(color) == 0:
            return

        color_lower = []  # 存储对应颜色hsv的最小范围
        color_upper = []  # 存储对应颜色hsv的最大范围
        try:
            for single_color in color:
                if not isinstance(single_color, tuple):
                    print("input color is wrong!")
                    return

                color_lower.append(single_color[0])
                color_upper.append(single_color[1])
        except Exception as e:
            print(e)
        finally:
            return color_lower, color_upper

    @staticmethod
    def list_transform_array(*data_list):
        """
        列表转换数组
        :param data_list:不确定个数参数
        :return:
        """
        data_array = []
        for single_data in data_list:
            data_array.append(np.array(single_data))
        return tuple(data_array)

    @staticmethod
    def get_hsv_image(image_path):
        """
        bgr转rgb
        :param image_path:图片路径
        :return:
        """
        image_bgr = cv2.imread(image_path)
        image_hsv = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2HSV)
        return image_hsv

    @staticmethod
    def list_to_contours_line(point_distance, *point_list):
        """
        列表转轮廓contours(线段)
        :param point_list:列表parameter1 = [point1, point2, point3.....], parameter2 = [point11, point21, point31.....]
        :return: [array([point1], [point2]), array([point3], [point4])].....
        """
        parameter_list = []

        index = 0
        point_contours = []
        tmp_point_list = []

        def euclidean_distance(x, y):
            distance = np.sqrt(np.sum(np.square(x - y)))
            return distance

        try:
            # 对每个传入的参数进行遍历
            for single_paratemeter in point_list:
                point_contours = point_contours.copy()
                point_contours.clear()
                # 对每个参数的列表进行遍历
                for single_point in single_paratemeter:
                    index += 1

                    # 构造线段
                    if index < 3:
                        tmp_point_list.append(single_point)

                    # 列表转array
                    if index % 2 == 0:
                        single_point_array = np.array([tmp_point_list.copy()])
                        point_contours.append(single_point_array)
                        tmp_point_list.clear()
                        index = 0

                    # 设置欧式距离大于50丢弃
                    if len(point_contours) == 2:
                        x_point, y_point = point_contours[0], point_contours[1]
                        distance = euclidean_distance(x_point, y_point)
                        if distance > point_distance:
                            continue

                parameter_list.append(point_contours)
        except Exception as e:
            print(e)
        finally:
            return tuple(parameter_list)

    @staticmethod
    def list_to_contours_point(*point_list):
        """
        列表转单点轮廓contours(点)
        :param point_list:列表parameter1 = [point1, point2, point3.....], parameter2 = [point11, point21, point31.....]
        :return: [array([point1]), array([point3])].....
        """
        parameter_list = []

        index = 0
        point_contours = []

        try:
            # 对每个传入的参数进行遍历
            for single_paratemeter in point_list:
                point_contours = point_contours.copy()
                point_contours.clear()

                # 对每个参数的列表进行遍历
                for single_point in single_paratemeter:
                    index += 1

                    # 构造点
                    point_contours.append(np.array([single_point]))
                parameter_list.append(point_contours)
        except Exception as e:
            print(e)
        finally:
            return tuple(parameter_list)

    @staticmethod
    def contours_to_single_contours(contours:list):
        """
        实现轮廓的提取,输入为提取后的轮廓列表-输出为单轮廓的点
        :return:
        """
        if len(contours) == 0:
            return
        tmp_point_list = []

        for single_line_point in contours:
            # 转换为列表
            location_list = single_line_point.tolist()
            lenght = len(location_list)

            # 长度为1：点，长度为2：线段，长度为3或以上：拐点
            for single_lenght in range(lenght):
                point_location_list = location_list[single_lenght][0]
                tmp_point_list.append([point_location_list])

        return [np.array(tmp_point_list)]

    @staticmethod
    def contours_to_mult_contours(contours:list):
        """
        实现轮廓的提取,输入为提取后的轮廓列表-输出为多轮廓的点
        :return:
        """
        if len(contours) == 0:
            return
        tmp_point_list = []
        final_point_list = []

        for single_line_point in contours:
            # 转换为列表
            location_list = single_line_point.tolist()
            lenght = len(location_list)

            # 长度为1：点，长度为2：线段，长度为3或以上：拐点
            for single_lenght in range(lenght):
                point_location_list = location_list[single_lenght][0]
                final_point_list.append(np.array([[point_location_list]]))

        return final_point_list

    @staticmethod
    def contours_to_list(contours: list, height):
        single_contours_list = []
        full_contours_list = []

        for single_line_point in contours:
            # 转换为列表
            location_list = single_line_point.tolist()
            lenght = len(location_list)

            # 另外开辟存放单独轮廓的内存
            single_contours_list = single_contours_list.copy()
            single_contours_list.clear()

            # 长度为1：点，长度为2：线段，长度为3或以上：拐点
            for single_lenght in range(lenght):
                point_location_list = location_list[single_lenght][0]

                # 检验点的格式，是否为x,y两个坐标值
                if len(point_location_list) != 2 or not isinstance(point_location_list, list):
                    print("exited point is not point")
                    continue

                # 替换坐标点的y值坐标-左上角顶点为原点转换为左下角顶点为原点
                point_location_list[0], point_location_list[1] = point_location_list[0], height - point_location_list[1]
                single_contours_list.append(point_location_list)

            full_contours_list.append(single_contours_list)
        return full_contours_list

    @staticmethod
    def division_endge_point(contours_list :list, width, height, pixel_range):
        """
        从轮廓列表中剔除边缘的点，并将其列表进行拆分
        :param contours_list:轮廓列表
        :return:
        """
        if not isinstance(contours_list, list):
            print("input is error!")
            return

        final_contours_lists = []            # 分割后的完整轮廓列表
        devision_contours_dict = {}          # 存放分割后的所有片段
        devision_contours_lists = []         # 存放分割的单个片段
        for single_contours_list in contours_list:
            if not isinstance(single_contours_list, list):
                continue

            devision_number = 0
            for point in single_contours_list:
                x_location, y_location = point[0], point[1]
                # 剔除靠近边缘的轮廓的像素点
                if x_location not in range(width-pixel_range, width) or x_location not in range(0, pixel_range) or \
                        y_location not in range(0, pixel_range) or y_location not in range(height-pixel_range, height):
                    devision_contours_lists.append(point)
                else:
                    devision_number += 1
                    devision_contours_dict[devision_number] = devision_contours_lists.copy()
                    devision_contours_lists.clear()

            # 针对单个轮廓的直接加入最终轮廓列表中
            if len(devision_contours_dict) == 0 and devision_number == 0:
                final_contours_lists.append(devision_contours_lists)
                continue

            # 多个轮廓的从字典中提取并存为多个子轮廓列表并加入最终轮廓列表中
            temp_devision_lists = []
            for index, value in enumerate(devision_contours_dict):
                temp_devision_lists.append(value)
            final_contours_lists.append(temp_devision_lists)

        return final_contours_lists

    # def get_contours_location(self, direction, longitude, latitude, numpy_list, scale):
    #     """
    #     位置计算
    #     :param direction: [0,0,0,1]，分别表示左上，右上，右下，左下
    #     :param longitude: 经度
    #     :param latitude: 纬度
    #     :return:
    #     """
    #     if not isinstance(direction, list) or len(direction) != 4:
    #         print("位置转化错误！")
    #         return
    #
    #     if direction.count(1) != 1:
    #         print("direction is wrong!")
    #         return
    #
    #     if direction.index(1) == 0:  # 左上
    #         numpy_list = numpy_list * scale
    #         x_size, y_size = numpy_list.size()
    #
    #         new_location = np.ones(x_size, y_size)
    #         numpy_location =  new_location - numpy_list
    #         return numpy_location
    #
    #     if direction.index(1) == 1:  #右上
    #
    #     if direction.index(1) == 2:  #右下
    #
    #     if direction.index(1) == 3:  #左下
    #
    #


if __name__ == "__main__":
    image = "/home/zhaokaiyue/Desktop/2.png"
    color = Utils.get_hsv_image(image)
    cv2.imshow("ss", color)
    cv2.waitKey()
    cv2.destroyWindow()
